package cn.laowen.basic.service.impl;

import cn.laowen.basic.constants.BaseConstant;
import cn.laowen.basic.dto.RegisterDto;
import cn.laowen.basic.exception.BusinessException;
import cn.laowen.basic.service.IVerifyCodeService;
import cn.laowen.basic.util.StrUtils;
import cn.laowen.basic.util.VerifyCodeUtils;
import cn.laowen.user.domain.User;
import cn.laowen.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 发送图形验证码
     * @param key
     * @return
     */
    @Override
    public String getImgCode(String key) {
        //空校验
        if (!StringUtils.hasLength(key)){
            throw new BusinessException("key不能为空!!!");
        }
        //生成长度为4的code
        String code = StrUtils.getComplexRandomString(4);
        System.out.println(code);
        //保存redis,设置过期时间
        redisTemplate.opsForValue().set(
                key,//前端传递的UUID
                code,//图形码
                5,//过期时间
                TimeUnit.MINUTES);//过期时间的单位
        /**
         * 使用2D引擎把code画成图
         * 把图使用Base64编码成字符串
         * 返回Base64编码的字符串
         */
        return VerifyCodeUtils.VerifyCode(100,30,code);//图形验证码的长,宽



    }

    /**
     * 发送短信验证码
     * @param registerDto
     */
    @Override
    public void smsCode(RegisterDto registerDto) {
        //一：校验
        //1.空校验
        String phone = registerDto.getPhone();//前端填写的电话
        String imageCodeKey = registerDto.getImageCodeKey();//前端存储图形验证码的key
        String imageCodeValue = registerDto.getImageCodeValue();//前端填入的图形验证码
        if (StringUtils.isEmpty(phone)
                ||StringUtils.isEmpty(imageCodeKey)
                ||StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("参数不能为空!!!");
        }
        //2.校验图形验证码，根据imageCodeKey从redis获取图形验证码
        Object imageCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        System.out.println("前端输入的验证码："+imageCodeValue);
        System.out.println("图形码中的验证码："+imageCodeTmp);
        //获取不到---图形验证码过期,提示重新获取
        if (imageCodeTmp == null){
            throw new BusinessException("图形验证码已过期,请重新获取");
        }
        //获取到了，比较图形验证码是否正确,不区分大小写
        if (!imageCodeTmp.toString().equalsIgnoreCase(imageCodeValue)){
            //不正确，提示输入图形验证码错误
            throw new BusinessException("验证码不正确,请重试");
        }

        //正确，往下走
        //3.校验手机号是否注册过了
        User userTmp = userMapper.loadByPhone(phone);
        //注册过了，提示登录
        if (userTmp!=null){
            throw new BusinessException("该用户已存在,请直接登录");
        }
        //。没有注册过，往下走
        //二：短信验证码逻辑
        //1.根据手机号拼接key，159:register，从redis获取曾今可能发送的短信验证码
        String key = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX +phone;
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        //1.1 获取到了
        String smsCode = "";//验证码
        if(smsCodeTmp !=null){
            //1.1.1 校验是否过了一分钟,重发时间 value  9527:232468742341657213
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);//上一次的验证码
            //小于一分钟,谨防别人刷新浏览器重新访问
            if(System.currentTimeMillis() - oldTime <1*60*1000){
                throw new BusinessException("小伙子我劝你不要搞事喔,一分钟还没到^.^");
            }

            //大于一分钟（说明还没有到3分钟，验证码还有效），
            //使用还没过期的验证码，刷新过期时间
            smsCode = smsCodeTmp.toString().split(":")[0];
        }else {

            //1.2 获取不到
            //1.2.1.生成新的短信验证码
            smsCode = StrUtils.getComplexRandomString(4);//长度为4的code
        }

        //三.存储redis 设置一个过期时间
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();//给验证码加上时间搓
        redisTemplate.opsForValue().set(
                key,
                smsCodeValue,
                3,
                TimeUnit.MINUTES);
        //四.发送短信
        //SmsUtils.sendSms(phone,"亲爱的用户,您好,您的验证码是:"+smsCode+"请在三分钟内完成注册");//发送短信到手机号
        System.out.println("亲，您的验证码是：" + smsCode + "。请在3分钟内使用！！");//打印短信验证码
    }
}
